package com.sky.service.user.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrdersMapper;
import com.sky.result.PageResult;
import com.sky.service.user.AddressBookService;
import com.sky.service.user.OrdersService;
import com.sky.service.user.ShoppingCartService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangqi
 * @date 2024/1/4 11:07
 */
@Slf4j
@Service
public class OrdersServiceImpl implements OrdersService {
    @Autowired
    private AddressBookService addressBookService;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private ShoppingCartService shoppingCartService;
    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Transactional
    @Override
    public OrderSubmitVO submitOrders(OrdersSubmitDTO ordersSubmitDTO) {
        //1.创建Orders对象
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);

        //2.设置用户id
        Long userId = BaseContext.getCurrentId();
        orders.setUserId(userId);

        //3.设置订单收件人的信息、地址信息
        AddressBook addressBook = addressBookService.findAddressById(orders.getAddressBookId());
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());
        orders.setConsignee(addressBook.getConsignee());


        //4.设置订单号、订单状态
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setStatus(Orders.PENDING_PAYMENT);   //未支付
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);

        //5.存储订单数据到orders表
        log.info("添加订单前");
        ordersMapper.insert(orders);
        log.info("添加订单后");

        //6.把该订单的商品（菜品、套餐）添加到订单详情表中
        //获取该用户的购物车数据
        List<ShoppingCart> shoppingCartList = shoppingCartService.list();
        //把购物车中的ShoppingCart转换为OrderDetail
        List<OrderDetail> orderDetailList = shoppingCartList.stream().map(shoppingCart -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart, orderDetail);
            orderDetail.setOrderId(orders.getId());
            return orderDetail;
        }).collect(Collectors.toList());

        //7.把订单详情数据添加到order_detail中
        orderDetailMapper.insertBench(orderDetailList);

        //8.删除购物车数据
        shoppingCartService.deleteAll();

        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        orderSubmitVO.setId(orders.getId());
        orderSubmitVO.setOrderNumber(orders.getNumber());
        orderSubmitVO.setOrderTime(orders.getOrderTime());
        orderSubmitVO.setOrderAmount(orders.getAmount());

        return orderSubmitVO;
    }

    @Override
    public PageResult historyOrders(Integer page, Integer pageSize, Integer status) {
        //1.开启分页
        PageHelper.startPage(page, pageSize);
        //2.查询订单
        Long userId = BaseContext.getCurrentId();
        Page<Orders> list = ordersMapper.findOrdersByUserId(userId, status);

        //3.把Orders转换为OrderVO类型
        List<OrderVO> orderVOList = list.stream().map(orders -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(orders, orderVO);
            //查询order_detail表，获取该订单的所有数据
            List<OrderDetail> orderDetailList = orderDetailMapper.findOrderDetailByOrderId(orders.getId());
            orderVO.setOrderDetailList(orderDetailList);
            return orderVO;
        }).collect(Collectors.toList());

        //4.构造返回结果
        PageResult pageResult = new PageResult();
        pageResult.setTotal(list.getTotal());
        pageResult.setRecords(orderVOList);

        return pageResult;
    }

    @Override
    public OrderVO findOrdersById(Long id) {
        //1.通过订单id查询订单数据
        Orders orders = ordersMapper.findOrdersById(id);
        //2.通过订单id获取订单详情数据
        List<OrderDetail> orderDetailList = orderDetailMapper.findOrderDetailByOrderId(id);
        //3.封装返回结果
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(orders, orderVO);
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    @Override
    public void cancel(Long id) {
        //取消订单：调用mapper做修改订单状态的操作
        ordersMapper.cancel(id);
    }


    @Override
    public PageResult pageQuery(OrdersPageQueryDTO ordersPageQueryDTO) {
        //1.开启分页
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        //2.设置userId
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());

        //3.查询orders表中满足条件的数据
        Page<Orders> list = ordersMapper.findOrdersByCondition(ordersPageQueryDTO);
        log.info("===管理端订单搜索结果：{}", list);
        //4.把Orders转换为OrderVO
        List<OrderVO> orderVOList = list.stream().map(orders -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(orders, orderVO);
            List<OrderDetail> orderDetailList = orderDetailMapper.findOrderDetailByOrderId(orders.getId());
            orderVO.setOrderDetailList(orderDetailList);
            return orderVO;
        }).collect(Collectors.toList());

        //5. 封装分页结果
        PageResult pageResult = new PageResult();
        pageResult.setTotal(list.getTotal());
        pageResult.setRecords(orderVOList);

        return pageResult;
    }


    @Override
    public OrderStatisticsVO statistics() {
        //1.统计待接单的数量
        Integer tobeConfirmedCount = ordersMapper.countStatus(Orders.TO_BE_CONFIRMED);
        //2.统计待派送的数量
        Integer confirmedCount = ordersMapper.countStatus(Orders.CONFIRMED);
        //3.统计派送中的数量
        Integer inProgressCount = ordersMapper.countStatus(Orders.DELIVERY_IN_PROGRESS);

        //4.封装返回结果
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        orderStatisticsVO.setToBeConfirmed(tobeConfirmedCount);
        orderStatisticsVO.setDeliveryInProgress(inProgressCount);
        orderStatisticsVO.setConfirmed(confirmedCount);

        return orderStatisticsVO;
    }

    @Override
    public void cancel(OrdersCancelDTO ordersCancelDTO) {
        Orders orders = new Orders();
        orders.setId(ordersCancelDTO.getId());
        orders.setCancelReason(ordersCancelDTO.getCancelReason());
        orders.setCancelTime(LocalDateTime.now());
        ordersMapper.updateCancel(orders);
    }

    @Override
    public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
        //创建Orders对象
        Orders orders = new Orders();
        orders.setId(ordersConfirmDTO.getId());
        orders.setStatus(Orders.CONFIRMED);

        //修改orders表中status的状态
        ordersMapper.update(orders);
    }

    @Override
    public void delivery(Long id) {
        //1.获取这个订单
        Orders orders = ordersMapper.findOrdersById(id);
        //2.判断订单是否存在，以及订单是否处于CONFIRMED状态，否词不能接单
        if (orders == null || orders.getStatus() != Orders.CONFIRMED) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        //3.创建一个Orders对象
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        ordersMapper.update(orders);
    }

    @Override
    public void complete(Long id) {
        //1.获取这个订单
        Orders orders = ordersMapper.findOrdersById(id);
        //2.判断订单是否存在，以及订单是否处于DELIVERY_IN_PROGRESS状态，否词不能完成
        if (orders == null || orders.getStatus() != Orders.DELIVERY_IN_PROGRESS) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        //3.重新给订单设置状态
        orders.setStatus(Orders.COMPLETED);
        orders.setDeliveryTime(LocalDateTime.now());

        ordersMapper.update(orders);
    }

    @Override
    public void reject(OrdersRejectionDTO ordersRejectionDTO) {
        //1.获取要拒绝的订单
        Orders orders = ordersMapper.findOrdersById(ordersRejectionDTO.getId());

        //2.判断订单是否存在，以及订单的状态是否是待接单，处在待接单才能拒绝，否则不能拒绝
        if (orders == null || !(orders.getStatus() == Orders.TO_BE_CONFIRMED)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        //3.设置订单的拒绝原因，设置订单状态为取消
        orders.setRejectionReason(ordersRejectionDTO.getRejectionReason());
        orders.setCancelReason(ordersRejectionDTO.getRejectionReason());
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelTime(LocalDateTime.now());

        ordersMapper.update(orders);
    }

    @Override
    public OrderReportVO orderReport(LocalDate begin, LocalDate end) {
        //1.创建一个集合，存储图表横轴显示的每一天的日期
        ArrayList<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }

        //2.获取begin~end之间每一天的总订单数、有效订单数
        List<Integer> totalCountList = new ArrayList<>();
        List<Integer> vaildCountList = new ArrayList<>();

        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);

            //查询date这一天中总订单数、有效订单数
            Integer totalCount = countByMap(beginTime, endTime, null);
            Integer vaildCount = countByMap(beginTime, endTime, Orders.COMPLETED);

            totalCountList.add(totalCount);
            vaildCountList.add(vaildCount);
        }

        //3.求begin~end这个时间段内所有订单数的总和、有效订单数的总和
        Integer totalCount = totalCountList.stream().reduce(Integer::sum).get();
        Integer vaildCount = vaildCountList.stream().reduce(Integer::sum).get();

        //4.订单完成率 = 有效订单数/总订单数 （注意：总订单数不能为0）
        Double orderCompletionRate = 0.0;
        if (totalCount != 0) {
            orderCompletionRate = vaildCount.doubleValue()/totalCount.intValue();
        }

        //5.封装返回结果
        OrderReportVO orderReportVO = OrderReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .validOrderCountList(StringUtils.join(vaildCountList, ","))
                .orderCountList(StringUtils.join(totalCountList, ","))
                .totalOrderCount(totalCount)
                .validOrderCount(vaildCount)
                .orderCompletionRate(orderCompletionRate)
                .build();

        return orderReportVO;
    }

    public Integer countByMap(LocalDateTime beginTime, LocalDateTime endTime, Integer status) {
        Map map = new HashMap();
        map.put("begin", beginTime);
        map.put("end", endTime);
        map.put("status", status);
        Integer count = ordersMapper.countByMap(map);
        return count;
    }
}
